/// Binary protocol helpers for scrcpy communication

pub fn write_16be(buf: &mut [u8], value: u16) {
    buf[0] = (value >> 8) as u8;
    buf[1] = value as u8;
}

pub fn write_32be(buf: &mut [u8], value: u32) {
    buf[0] = (value >> 24) as u8;
    buf[1] = (value >> 16) as u8;
    buf[2] = (value >> 8) as u8;
    buf[3] = value as u8;
}

pub fn write_64be(buf: &mut [u8], value: u64) {
    buf[0] = (value >> 56) as u8;
    buf[1] = (value >> 48) as u8;
    buf[2] = (value >> 40) as u8;
    buf[3] = (value >> 32) as u8;
    buf[4] = (value >> 24) as u8;
    buf[5] = (value >> 16) as u8;
    buf[6] = (value >> 8) as u8;
    buf[7] = value as u8;
}

pub fn read_16be(buf: &[u8]) -> u16 {
    ((buf[0] as u16) << 8) | (buf[1] as u16)
}

pub fn read_32be(buf: &[u8]) -> u32 {
    ((buf[0] as u32) << 24) | ((buf[1] as u32) << 16) | ((buf[2] as u32) << 8) | (buf[3] as u32)
}

pub fn read_64be(buf: &[u8]) -> u64 {
    ((buf[0] as u64) << 56)
        | ((buf[1] as u64) << 48)
        | ((buf[2] as u64) << 40)
        | ((buf[3] as u64) << 32)
        | ((buf[4] as u64) << 24)
        | ((buf[5] as u64) << 16)
        | ((buf[6] as u64) << 8)
        | (buf[7] as u64)
}

pub fn write_position(buf: &mut [u8], x: i32, y: i32, w: u16, h: u16) {
    write_32be(&mut buf[0..4], x as u32);
    write_32be(&mut buf[4..8], y as u32);
    write_16be(&mut buf[8..10], w);
    write_16be(&mut buf[10..12], h);
}

pub fn write_string(text: &str, max_len: usize, buf: &mut Vec<u8>) {
    let bytes = text.as_bytes();
    let len = bytes.len().min(max_len);
    
    // Write string length (4 bytes)
    let len_bytes = (len as u32).to_be_bytes();
    buf.extend_from_slice(&len_bytes);
    
    // Write string content
    buf.extend_from_slice(&bytes[..len]);
}

pub fn read_string(buf: &[u8]) -> Result<(String, usize), std::string::FromUtf8Error> {
    if buf.len() < 4 {
        return Ok((String::new(), 0));
    }
    
    let len = read_32be(&buf[0..4]) as usize;
    if buf.len() < 4 + len {
        return Ok((String::new(), 4));
    }
    
    let text = String::from_utf8(buf[4..4 + len].to_vec())?;
    Ok((text, 4 + len))
}

/// Convert float to unsigned 16-bit fixed point
pub fn float_to_u16fp(value: f32) -> u16 {
    let clamped = value.max(0.0).min(1.0);
    (clamped * 0xFFFF as f32) as u16
}

/// Convert float to signed 16-bit fixed point
pub fn float_to_i16fp(value: f32) -> i16 {
    let clamped = value.max(-1.0).min(1.0);
    (clamped * 0x7FFF as f32) as i16
}

/// Convert unsigned 16-bit fixed point to float
pub fn u16fp_to_float(value: u16) -> f32 {
    value as f32 / 0xFFFF as f32
}

/// Convert signed 16-bit fixed point to float
pub fn i16fp_to_float(value: i16) -> f32 {
    value as f32 / 0x7FFF as f32
}